use strict;
use warnings;
use Math::Combinatorics;
use Math::NumberCruncher;
use Data::Dumper;
use Time::HiRes qw(gettimeofday tv_interval);
use Benchmark qw( cmpthese ) ;

#my $pept = 'O(177)S(23)OO(122)OOYOOT(21)OO';
#my $pept = 'A(737)TSSSSGS(21)LSATGR';

sub peptide_collection{
    my $pept = 'A(737)TSSSSGS(21)LSATGR';
	#my $pept = $_[0];
	#Limitado a 1/dos chemtags por aa o 1 chemtag + 1 phos
	#			2/Los chemtag no cambian de sitio
	my @posibles_fosfo_sites;
	my @posibles_deshidrat_sites;
	my $num_fosfos = 0;
	my $num_deshidrats = 0;
	my $num_chemtag = 0;
	my $alrdy_one;

	my (@aas, @mods);
	my $aa_num = 0;
	while($pept){ #=~ /\w/
		my ($aa, $mod);
		if($pept =~ s/^(\w)\((\w+),(\w+)\)//){    #Limitado a 2 chemtags por aa.
			$alrdy_one = 0;
			$aa = $1;
			my @mod1 = ($2, $3);
			push @aas, $aa;
			#Calculo el numero de fosfos/chemtags/DH
            foreach(@mod1){
                if($_ == 21){
                    $num_fosfos++;
                }
                elsif($_ == 23){
                    $num_deshidrats++;
                }
                else {
                    if ($alrdy_one){
						my $frst = pop @mods;
						push @mods, "$frst,$_";
					} else {
						push @mods, $_;
						$alrdy_one = 1;
					}
                    if($aa_num > 0){        #Si hay chemtag en un aa no N-terminal,
                        $aa_num++;          #no se puede modificar con nada mas
                        next;               #ojo este next tiene que ser un label
                    }
                }
            }
		}
        elsif ($pept =~ s/^(\w)\((\w+)\)//){
			$aa = $1;
			$mod = $2;
			push @aas, $aa;
			push @mods, $mod;
			#Calculo el numero de fosfos/chemtags/DH
			if ($mod == 21){
				$num_fosfos++;
			}
			elsif ($mod == 23){
				$num_deshidrats++;
			}
			elsif ($mod == 214 or $mod == 737){
				#push @mods, $mod;
				$num_chemtag++;
				if ($aa_num > 0){        #Si hay chemtag en un aa no N-terminal,
					$aa_num++;           #no se puede modificar con nada mas
					next;
				}
			}
        }
		else{
			$pept =~ s/^(\w)//;
			$aa = $1;
			$mod = '';
			push @aas, $aa;
			push @mods, $mod;
		}

		if($aa =~ /[S,T,Y]/){
			push @posibles_fosfo_sites, $aa_num;
		}
		if($aa =~ /[S,T]/){
			push @posibles_deshidrat_sites, $aa_num;
		}
		$aa_num++;
	}
    #my $t1 = [gettimeofday];
	#Obtengo las diferentes combinaciones de fosforilados y deshidratados
	my @combins_fosfo;
	my @combins_deshidrats;

	my $combin_1 = Math::Combinatorics->new(count => $num_fosfos,
											 data => [@posibles_fosfo_sites],);
	while(my @combo1 = $combin_1->next_combination){
		push @combins_fosfo, \@combo1;
	}
	my $combin_2 = Math::Combinatorics->new(count => $num_deshidrats,
											 data => [@posibles_deshidrat_sites],);

	while(my @combo2 = $combin_2->next_combination){
		push @combins_deshidrats, \@combo2;
	}

    #my $t2 = [gettimeofday];

	my @combins_peptidos;
	if(@combins_fosfo and @combins_deshidrats){
		#print "Hay phospho, DH y chemtag\t";
		foreach my $fos(@combins_fosfo){
			my %usados;
			my @fos = @$fos;
			foreach my $f(@fos){
				$usados{$f} = 1;
			}
			LABEL1:
			foreach my $deshidrat(@combins_deshidrats){
				my @deshidrats = @$deshidrat;
				foreach my $d(@deshidrats){
					if(defined $usados{$d}){
						next LABEL1;
					}
				}
				#nuevo array de modificaciones para construir el peptido modificado
				my @mods_new;
				for (0..$#mods){         #Recupero las modificaciones no phospho o DH (chemtag,MetOx,...)
					if($mods[$_]){
						unless(($mods[$_] eq '21') or ($mods[$_] eq '23')){
							$mods_new[$_] = "($mods[$_])";
						}
					}
				}
				foreach (@fos){
					if($mods_new[$_]){
						my $t = $mods_new[$_];
						$t =~ s/[\(,\)]//g;
						$mods_new[$_] = "($t,21)";
					}
					else{
						$mods_new[$_]= '(21)';
					}
				}
				foreach (@deshidrats){
					if($mods_new[$_]){
						my $t = $mods_new[$_];
						$t =~ s/[\(,\)]//g;
						$mods_new[$_] = "($t,23)";
					}
					else{
						$mods_new[$_] = '(23)';
					}
				}
				#Genero el peptido
				my $pept_string = get_pept_string(\@aas, \@mods_new);
				push @combins_peptidos, $pept_string;
			}
		}
	}
	elsif (@combins_fosfo){
		#print "solo fosfo\t";
		foreach my $fos(@combins_fosfo){
			my @fos = @$fos;
			# Nuevo array de modificaciones para construir el peptido modificado
			my @mods_new;
			# Recupero las modificaciones no phospho o DH (chemtag,MetOx,...)
			for(0..$#mods){
				if($mods[$_]){
					unless(($mods[$_] eq '21') or ($mods[$_] eq '23')){
						$mods_new[$_] = "($mods[$_])";
					}
				}
			}
			foreach (@fos){
				if($mods_new[$_]){
					my $t = $mods_new[$_];
					$t =~ s/[\(,\)]//g;
					$mods_new[$_] = "($t,21)";
				}
				else{
					$mods_new[$_] = '(21)';
				}
			}
			#Genero el peptido
			my $pept_string = get_pept_string(\@aas, \@mods_new);
			push @combins_peptidos, $pept_string;
		}
	}
	elsif (@combins_deshidrats){
		#print "solo DH\t";
		foreach my $deshidrat(@combins_deshidrats){
			my @deshidrats = @$deshidrat;
			#Genero nuevo array de modificaciones para construir el peptido modificado
			my @mods_new;
			#Recupero las modificaciones no phospho o DH (chemtag,MetOx,...)
			for(0..$#mods){
				if($mods[$_]){
					unless(($mods[$_]==21) or ($mods[$_]==23)){
						$mods_new[$_] = "($mods[$_])";
					}
				}
			}
			foreach (@deshidrats){
				if($mods_new[$_]){
					my $t = $mods_new[$_];
					$t =~ s/[\(,\)]//g;
					$mods_new[$_] = "($t,23)";
				}
				else{
					$mods_new[$_] = '(23)';
				}
			}
			#Genero el peptido
			my $pept_string = get_pept_string(\@aas, \@mods_new);
			push @combins_peptidos, $pept_string;
		}
	}
	else{
		push @combins_peptidos, $_[0];
	}
    #my $t3 = [gettimeofday];
    #
    #print 't1 ', Dumper (tv_interval($t1, $t0)), "\n";
    #print 't2 ', Dumper (tv_interval($t2, $t1)), "\n";
    #print 't3 ', Dumper (tv_interval($t3, $t2)), "\n";

	return @combins_peptidos;
}

sub get_pept_string{
	my @aas = @{$_[0]};
	my @mods_new = @{$_[1]};
	my $pept_string = '';
	for(0..$#aas){
		if($mods_new[$_]){
			$pept_string = $pept_string . $aas[$_] . $mods_new[$_];
		}
		else{
			$pept_string = $pept_string . $aas[$_];
		}
	}
	return $pept_string
}                                                                                    ####226 lineas



sub peptide_collection_2{
	#my $pept = $_[0];
    my $pept = 'A(737)TSSSSGS(21)LSATGR';
    my @players;
    my @skeleton;
    my @others;

    my $aa_num = 0;
    while($pept){
		my ($aa, $mod);
        my $forplay;
		if($pept =~ s/^(\w)\((\w+),(\w+)\)//){
            my @temp = ();
            push @skeleton, $1;
            if ($1 ~~ ['S','T','Y']){$forplay = 0};
            my @mods = ($2, $3);
            foreach (@mods){
                if (($_ == 21) or ($_ == 23)){
                    $forplay = $_;
                }
                else{
                    push @temp, $_;
                }
            $others[$aa_num] = join ',', @temp;
            }
        }
        elsif ($pept =~ s/^(\w)\((\w+)\)//){
			push @skeleton, $1;
            if ($1 ~~ ['S','T','Y']){$forplay = 0};
			if (($2 == 21) or ($2 == 23)){
                $forplay = $2;
            }
            else{
                $others[$aa_num] = $2;
            }
        }
		else{
			$pept =~ s/^(\w)//;
            if ($1 ~~ ['S','T','Y']){$forplay = 0};
			push @skeleton, $1;
        }
        if (defined($forplay)){push @players, $forplay};
        $aa_num++;
    }

    my @fullcombin = permute(@players);
    my %filtro;
    foreach(@fullcombin){$filtro{join ',', @$_} = $_};
    my @combin = values %filtro;

    #print Dumper (@combin), "\n";

    my @colection;
    foreach my $comb(@combin){
        my @newsec;
        my $count = 0;
        foreach my $aa (@skeleton){
            push @newsec, $aa;
            my $modp = '';
            my $text;
            my $modo = '';
            if (defined($others[$count])){
                $text = $others[$count];
            }
            if ($aa ~~ ['S','T','Y']){
                $modp = shift @$comb;
                unless ($modp eq '0'){
                    if (defined $text){
                        $text .= ",$modp";
                    }
                    else{
                        $text = $modp;
                    }
                }
            }
            if (defined $text){
                push @newsec, "($text)";
            }
            $count++;
        }
        my $combination = join '', @newsec;
        unless ($combination =~ /Y(\(23\,|\(23\)|\([0-9]+\,23)/){
            push @colection, $combination;
        }
    }
    return @colection;
}                                                                                   #####96 lineas

sub peptide_collection_3{
	#my $pept = $_[0];
    my $pept = 'A(737)TSSSSGS(21)LSATGR';
    my @players;
    my @skeleton;
    my @others;

    my $aa_num = 0;
    while($pept){
		my ($aa, $mod);
        my $forplay;
		if($pept =~ s/^(\w)\((\w+),(\w+)\)//){
            my @temp = ();
            push @skeleton, $1;
            if ($1 ~~ ['S','T','Y']){$forplay = '0'};
            my @mods = ($2, $3);
            foreach (@mods){
                if (($_ == 21) or ($_ == 23)){
                    $forplay = $_;
                }
                else{
                    push @temp, $_;
                }
            $others[$aa_num] = join ',', @temp;
            }
        }
        elsif ($pept =~ s/^(\w)\((\w+)\)//){
			push @skeleton, $1;
            if ($1 ~~ ['S','T','Y']){$forplay = '0'};
			if (($2 == 21) or ($2 == 23)){
                $forplay = $2;
            }
            else{
                $others[$aa_num] = $2;
            }
        }
		else{
			$pept =~ s/^(\w)//;
            if ($1 ~~ ['S','T','Y']){$forplay = '0'};
			push @skeleton, $1;
        }
        if (defined($forplay)){push @players, $forplay};
        $aa_num++;
    }

    my %filtro;
    my $combinat = Math::Combinatorics->new(data => [@players]);
    while(my @perm = $combinat->next_permutation){
        $filtro{join ',', @perm} = \@perm;
    }
    my @combin = values %filtro;

    #print Dumper (@combin), "\n";

    my @colection;
    foreach my $comb(@combin){
        my $newsec = '';
        my $count = 0;
        foreach my $aa (@skeleton){
            $newsec .= $aa;
            my $modp = '';
            my $text;
            if (defined($others[$count])){
                $text = $others[$count];
            }
            if ($aa ~~ ['S','T','Y']){
            #if ('STY' =~ /$aa/){
                $modp = shift @{$comb};
                unless ($modp eq '0'){
                    if (defined $text){
                        $text .= ",$modp";
                    }
                    else{
                        $text = $modp;
                    }
                }
            }
            if (defined $text){
                $newsec .= "($text)";
            }
            $count++;
        }

        unless ($newsec =~ /Y(\(23\,|\(23\)|\([0-9]+\,23)/){
            push @colection, $newsec;
        }
    }
    return @colection;
}

sub peptide_collection_4{
    my $t0 = [gettimeofday];
	#my $pept = $_[0];
    my $pept = 'A(737)TSSSSGS(21)LSATGR';
    my @players;
    my @skeleton;
    my @others;

    my $aa_num = 0;
    my ($aa, $mod);
    while($pept){
        my $forplay;
		if($pept =~ s/^(\w)\((\w+),(\w+)\)//){
            my @temp = ();
            push @skeleton, $1;
            if ($1 ~~ ['S','T','Y']){$forplay = 0};
            my @mods = ($2, $3);
            foreach (@mods){
                if (($_ == 21) or ($_ == 23)){
                    $forplay = $_;
                }
                else{
                    push @temp, $_;
                }
            $others[$aa_num] = join ',', @temp;
            }
        }
        elsif ($pept =~ s/^(\w)\((\w+)\)//){
			push @skeleton, $1;
            if ($1 ~~ ['S','T','Y']){
                if (($2 == 21) or ($2 == 23)){
                    $forplay = $2;
                }else{
                    $forplay = 0;
                }
            }
            else{
                $others[$aa_num] = $2;
            }
        }
		else{
			$pept =~ s/^(\w)//;
            if ($1 ~~ ['S','T','Y']){$forplay = 0};
			push @skeleton, $1;
        }
        if (defined($forplay)){push @players, $forplay};
        $aa_num++;
    }
    my $t1 = [gettimeofday];
    my %filtro;
    my $combinat = Math::Combinatorics->new(data => [@players]);
    while(my @perm = $combinat->next_permutation){
        $filtro{join ',', @perm} = \@perm;
    }
    my @combin = values %filtro;

    my $t2 = [gettimeofday];
    #print Dumper (@combin), "\n";

    my @colection;
    my $newsec;
    my $count;
    my $modp;
    foreach my $comb(@combin){
        $newsec = '';
        $count = 0;
        foreach my $aa (@skeleton){
            $newsec .= $aa;
            $modp = '';
            my $text;
            if (defined($others[$count])){
                $text = $others[$count];
            }
            if ($aa ~~ ['S','T','Y']){
                $modp = shift @{$comb};
                unless ($modp eq '0'){
                    if (defined $text){
                        $text .= ",$modp";
                    }
                    else{
                        $text = $modp;
                    }
                }
            }
            if (defined $text){
                $newsec .= "($text)";
            }
            $count++;
        }

        unless ($newsec =~ /Y(\(23\,|\(23\)|\([0-9]+\,23)/){
            push @colection, $newsec;
        }
    }
    #my $t3 = [gettimeofday];
    #
    #print 't1 ', Dumper (tv_interval($t1, $t0)), "\n";
    #print 't2 ', Dumper (tv_interval($t2, $t1)), "\n";
    #print 't3 ', Dumper (tv_interval($t3, $t2)), "\n";


    return @colection;
}

sub peptide_collection_5{
    my $pept = 'A(737)TSSSSGS(21)LSATGR';
	#my $pept = $_[0];
	#Limitado a 1/dos chemtags por aa o 1 chemtag + 1 phos
	#			2/Los chemtag no cambian de sitio
	my @posibles_fosfo_sites;
	my @posibles_deshidrat_sites;
	my $num_fosfos = 0;
	my $num_deshidrats = 0;
	my $num_chemtag = 0;
	my $alrdy_one;

	my (@aas, @mods);
	my $aa_num = 0;
    my $aa;
	while($pept){ #=~ /\w/
		if($pept =~ s/^(\w)\((\w+),(\w+)\)//){    #Limitado a 2 chemtags por aa.
			$alrdy_one = 0;
			my @mod1 = ($2, $3);
            $aa = $1;
			push @aas, $1;
			#Calculo el numero de fosfos/chemtags/DH
            foreach(@mod1){
                if($_ == 21){
                    $num_fosfos++;
                }
                elsif($_ == 23){
                    $num_deshidrats++;
                }
                else {
                    if ($alrdy_one){
						my $frst = pop @mods;
						push @mods, "$frst,$_";
					} else {
						push @mods, $_;
						$alrdy_one = 1;
					}
                    if($aa_num > 0){        #Si hay chemtag en un aa no N-terminal,
                        $aa_num++;          #no se puede modificar con nada mas
                        next;               #ojo este next tiene que ser un label
                    }
                }
            }
		}
        elsif ($pept =~ s/^(\w)\((\w+)\)//){
			$aa = $1;
            push @aas, $1;
			#Calculo el numero de fosfos/chemtags/DH
			if ($2 == 21){
                push @mods, '';
				$num_fosfos++;
			}
			elsif ($2 == 23){
                push @mods, '';
				$num_deshidrats++;
			}
			elsif ($2 == 214 or $2 == 737){
				push @mods, $2;
				$num_chemtag++;
				if ($aa_num > 0){        #Si hay chemtag en un aa no N-terminal,
					$aa_num++;           #no se puede modificar con nada mas
					next;
				}
			}
        }
		else{
			$pept =~ s/^(\w)//;
            $aa = $1;
			push @aas, $1;
			push @mods, '';
		}

		if($aa =~ /[S,T,Y]/){
			push @posibles_fosfo_sites, $aa_num;
		}
		if($aa =~ /[S,T]/){
			push @posibles_deshidrat_sites, $aa_num;
		}
		$aa_num++;
	}
    #my $t1 = [gettimeofday];
	#Obtengo las diferentes combinaciones de fosforilados y deshidratados
	my @combins_fosfo;
	my @combins_deshidrats;

	my $combin_1 = Math::Combinatorics->new(count => $num_fosfos,
											 data => [@posibles_fosfo_sites],);
	while(my @combo1 = $combin_1->next_combination){
		push @combins_fosfo, \@combo1;
	}
	my $combin_2 = Math::Combinatorics->new(count => $num_deshidrats,
											 data => [@posibles_deshidrat_sites],);

	while(my @combo2 = $combin_2->next_combination){
		push @combins_deshidrats, \@combo2;
	}

   	my @combins_peptidos;
	if(@combins_fosfo and @combins_deshidrats){
		#print "Hay phospho, DH y chemtag\t";
		foreach my $fos(@combins_fosfo){
			my %usados;
			my @fos = @$fos;
			foreach my $f(@fos){
				$usados{$f} = 1;
			}
			LABEL1:
			foreach my $deshidrat(@combins_deshidrats){
				my @deshidrats = @$deshidrat;
				foreach my $d(@deshidrats){
					if(defined $usados{$d}){
						next LABEL1;
					}
				}
				#nuevo array de modificaciones para construir el peptido modificado
				my @mods_new;
				for (0..$#mods){         #Recupero las modificaciones no phospho o DH (chemtag,MetOx,...)
					if($mods[$_]){
                        $mods_new[$_] = "($mods[$_])";
					}
				}
				foreach (@fos){
					if($mods_new[$_]){
						my $t = $mods_new[$_];
						$t =~ s/[\(,\)]//g;
						$mods_new[$_] = "($t,21)";
					}
					else{
						$mods_new[$_]= '(21)';
					}
				}
				foreach (@deshidrats){
					if($mods_new[$_]){
						my $t = $mods_new[$_];
						$t =~ s/[\(,\)]//g;
						$mods_new[$_] = "($t,23)";
					}
					else{
						$mods_new[$_] = '(23)';
					}
				}
				#Genero el peptido
				my $pept_string = get_pept_string(\@aas, \@mods_new);
				push @combins_peptidos, $pept_string;
			}
		}
	}
	elsif (@combins_fosfo){
		#print "solo fosfo\t";
		foreach my $fos(@combins_fosfo){
			my @fos = @$fos;
			# Nuevo array de modificaciones para construir el peptido modificado
			my @mods_new;
			# Recupero las modificaciones no phospho o DH (chemtag,MetOx,...)
			for(0..$#mods){
				if($mods[$_]){
					$mods_new[$_] = "($mods[$_])";
				}
			}
			foreach (@fos){
				if($mods_new[$_]){
					my $t = $mods_new[$_];
					$t =~ s/[\(,\)]//g;
					$mods_new[$_] = "($t,21)";
				}
				else{
					$mods_new[$_] = '(21)';
				}
			}
			#Genero el peptido
			my $pept_string = get_pept_string(\@aas, \@mods_new);
			push @combins_peptidos, $pept_string;
		}
	}
	elsif (@combins_deshidrats){
		#print "solo DH\t";
		foreach my $deshidrat(@combins_deshidrats){
			my @deshidrats = @$deshidrat;
			#Genero nuevo array de modificaciones para construir el peptido modificado
			my @mods_new;
			#Recupero las modificaciones no phospho o DH (chemtag,MetOx,...)
			for(0..$#mods){
				if($mods[$_]){
					$mods_new[$_] = "($mods[$_])";
				}
			}
			foreach (@deshidrats){
				if($mods_new[$_]){
					my $t = $mods_new[$_];
					$t =~ s/[\(,\)]//g;
					$mods_new[$_] = "($t,23)";
				}
				else{
					$mods_new[$_] = '(23)';
				}
			}
			#Genero el peptido
			my $pept_string = get_pept_string(\@aas, \@mods_new);
			push @combins_peptidos, $pept_string;
		}
	}
	else{
		push @combins_peptidos, $_[0];
	}
   	return @combins_peptidos;
}


sub peptide_collection_6{
    my $pept = 'A(737)TSSSSGS(21)LSATGR';
	#my $pept = $_[0];
	#Limitado a 1/dos chemtags por aa o 1 chemtag + 1 phos
	#			2/Los chemtag no cambian de sitio
	my @posibles_fosfo_sites;
	my @posibles_deshidrat_sites;
	my $num_fosfos = 0;
	my $num_deshidrats = 0;
	my $num_chemtag = 0;
	my $alrdy_one;
	my (@aas, @mods);
	my $aa_num = 0;
    my $aa;
	while($pept){ #=~ /\w/
		if($pept =~ s/^(\w)\((\w+),(\w+)\)//){    #Limitado a 2 chemtags por aa.
			$alrdy_one = 0;
			my @mod1 = ($2, $3);
            $aa = $1;
			push @aas, $1;
			#Calculo el numero de fosfos/chemtags/DH
            foreach(@mod1){
                if($_ == 21){
                    $num_fosfos++;
                }
                elsif($_ == 23){
                    $num_deshidrats++;
                }
                else {
                    if ($alrdy_one){
						my $frst = pop @mods;
						push @mods, "$frst,$_";
					} else {
						push @mods, $_;
						$alrdy_one = 1;
					}
                    if($aa_num > 0){        #Si hay chemtag en un aa no N-terminal,
                        $aa_num++;          #no se puede modificar con nada mas
                        next;               #ojo este next tiene que ser un label
                    }
                }
            }
		}
        elsif ($pept =~ s/^(\w)\((\w+)\)//){
			$aa = $1;
            push @aas, $aa;
			#Calculo el numero de fosfos/chemtags/DH
			if ($2 == 21){
                push @mods, '';
				$num_fosfos++;
			}
			elsif ($2 == 23){
                push @mods, '';
				$num_deshidrats++;
			}
			else{
				push @mods, $2;
				$num_chemtag++;
				if ($aa_num > 0){        #Si hay chemtag en un aa no N-terminal,
					$aa_num++;           #no se puede modificar con nada mas
					next;
				}
			}
        }
		else{
			$pept =~ s/^(\w)//;
            $aa = $1;
			push @aas, $1;
			push @mods, '';
		}

        if($aa =~ /[S,T,Y]/){
			push @posibles_fosfo_sites, $aa_num;
            if($aa =~ /[S,T]/){
                push @posibles_deshidrat_sites, $aa_num;
            }
		}
		$aa_num++;
	}
    #my $t1 = [gettimeofday];
	#
	my @combins_fosfo;
	my @combins_deshidrats;

    #print 'fosfos ', $num_fosfos, "\n";
    #print Dumper (@posibles_fosfo_sites), "\n";
    #print 'deshidr ', $num_deshidrats, "\n";
    #print Dumper (@posibles_fosfo_sites), "\n";

	my $combin_1 = Math::Combinatorics->new(count => $num_fosfos,
											 data => [@posibles_fosfo_sites],);
	while(my @combo1 = $combin_1->next_combination){
		push @combins_fosfo, \@combo1;
	}
	my $combin_2 = Math::Combinatorics->new(count => $num_deshidrats,
											 data => [@posibles_deshidrat_sites],);

	while(my @combo2 = $combin_2->next_combination){
		push @combins_deshidrats, \@combo2;
	}

   	my @combins_peptidos;
	if(@combins_fosfo and @combins_deshidrats){
        print 'here ++';
		foreach my $fos(@combins_fosfo){
			my %usados;
			my @fos = @$fos;
			foreach my $f(@fos){
				$usados{$f} = 1;
			}
			LABEL1:
			foreach my $deshidrat(@combins_deshidrats){
				my @deshidrats = @$deshidrat;
				foreach my $d(@deshidrats){
					if(defined $usados{$d}){
						next LABEL1;
					}
				}
				my @mods_new;
				for (0..$#mods){
					if($mods[$_]){
                        $mods_new[$_] = "($mods[$_])";
					}
				}
				foreach (@fos){
					if($mods_new[$_]){
						my $t = $mods_new[$_];
						$t =~ s/[\(,\)]//g;
						$mods_new[$_] = "($t,21)";
					}
					else{
						$mods_new[$_]= '(21)';
					}
				}
				foreach (@deshidrats){
					if($mods_new[$_]){
						my $t = $mods_new[$_];
						$t =~ s/[\(,\)]//g;
						$mods_new[$_] = "($t,23)";
					}
					else{
						$mods_new[$_] = '(23)';
					}
				}
				#Genero el peptido
				my $pept_string = get_pept_string(\@aas, \@mods_new);
				push @combins_peptidos, $pept_string;
			}
		}
	}
	elsif (@combins_fosfo){
        print 'here +-';
		foreach my $fos(@combins_fosfo){
			my @fos = @$fos;
			my @mods_new;
			#
			for(0..$#mods){
				if($mods[$_]){
					$mods_new[$_] = "($mods[$_])";
				}
			}
			foreach (@fos){
				if($mods_new[$_]){
					my $t = $mods_new[$_];
					$t =~ s/[\(,\)]//g;
					$mods_new[$_] = "($t,21)";
				}
				else{
					$mods_new[$_] = '(21)';
				}
			}
			my $pept_string = get_pept_string(\@aas, \@mods_new);
			push @combins_peptidos, $pept_string;
		}
	}
	elsif (@combins_deshidrats){
        print 'here -+';
		foreach my $deshidrat(@combins_deshidrats){
			my @deshidrats = @$deshidrat;
			my @mods_new;
            #
			for(0..$#mods){
				if($mods[$_]){
					$mods_new[$_] = "($mods[$_])";
				}
			}
			foreach (@deshidrats){
				if($mods_new[$_]){
					my $t = $mods_new[$_];
					$t =~ s/[\(,\)]//g;
					$mods_new[$_] = "($t,23)";
				}
				else{
					$mods_new[$_] = '(23)';
				}
			}
			my $pept_string = get_pept_string(\@aas, \@mods_new);
			push @combins_peptidos, $pept_string;
		}
	}
	else{
		push @combins_peptidos, $_[0];
	}
   	return @combins_peptidos;
}

#print Dumper peptde_collection_2('O(177)S(23)OO(122)OSOYOOT(21)OO');
#print "1\n", Dumper peptide_collection('A(737)TSSSSGS(21)LSATGR');
#print '2\n', Dumper peptide_collection_2('A(737)TSSSSGS(21)LSATGR');
#print "3\n", Dumper peptide_collection_3('A(737)TSSSSGS(21)LSATGR');
#print "4\n", Dumper peptide_collection_4('A(737)TSSSSGS(21)LSATGR');
#print "5\n", Dumper peptide_collection_5('A(737)TSSSSGS(21)LSATGR');
print "6\n", Dumper peptide_collection_6('A(737)TSSSSGS(21)LSATGR');
__END__

cmpthese(20, {
        #a => \&peptide_collection,
        #b => \&peptide_collection_2,
        c => \&peptide_collection_3,
        d => \&peptide_collection_4,      #en desarrollo lenta ln 430
        #e => \&peptide_collection_5,
        #f => \&peptide_collection_6
        } );



1;
